<?php
/**
 * 
 * Class for load_textdomain
 * @author "Ralf Albert"
 * @package textdomain_class
 * @version 0.2
 *
 */
class Textdomain
{
	var $args, $path, $add_path, $domain, $textdomain, $locale, $debug;
	var $mofiles = array(); 
	var $all_domains = array();
	var $all_locales = array();
	var $guesseddomains = array();
	
	/**
	 * 
	 * Constructor (PHP4-Style)
	 * @param array | string $args
	 */
	function Textdomain( $args ){
		// Use this class only with WordPress
		$this->isWP();
		
		if( !isset( $args ) ){
			wp_die( __('At least we will need some arguments...') );
		}
		else {
			$this->args = $args;
			$this->parseArgs();
			
			$this->setLocale( $this->locale );
		}
	}
	
	/**
	 * 
	 * Checks if the WordPress-Core is loaded. Die if no WP core was found
	 * 
	 * @param none
	 * @return bool true
	 */	
	function isWP(){
		if( !function_exists( 'add_action' ) ){
			die('Use this class only within WordPress!');
		}
		else {
			return true;
		}
	}
	
	/**
	 * 
	 * Parse the given arguments
	 * 
	 * @param string $args | array $args
	 * @return string $path, $domain
	 */
	function parseArgs(){
		if( is_array( $this->args ) ){

			// There are more information
			// I hope there are $path, $domain and/or $addpath 
			extract( $this->args );
			
				// At least we will need the path
				if( !isset( $path ) ){
					wp_die( __('<strong>Error:</strong> No path or filename given.') );
				}
				// OK, we have a path-info. But is it a file or a directory? We need a directory
				elseif( is_file( $path ) ){
					$path = dirname( $path );
				}
			
			// Now we have some data, we have to pick what we need
			$this->path = $path;
				
				// if there is an additional path-info, add it to $path
				if( $addpath ){
					$this->path .= $addpath;
					$this->add_path = $addpath;
				}
			
			$this->domain = $domain;
			
			unset($path, $addpath, $domain);
			
			return;
			
		}
		else {
			// Maybe $args is not an array, so we only have the path (I hope so, it is the path)

			// But we have to be sure it is a file or directory
			if( is_file( $this->args ) || is_dir( $this->args ) ){
				$this->path = $this->args;
				
				if( is_file( $this->path ) ){
					$this->path = dirname( $this->path );
				}
				
				return;
			}
			// we have received something strange
			else {
				wp_die( __('<strong>Error:</strong> Please check your arguments. <em>"'.htmlentities( $this->args ).'"</em> is not a valid and/or fully qualified file- or directoryname.') );
			}
		}
		
	}
	
	/* --- Mo-Files ---------------------------------------------- */	
	
	/**
	 * 
	 * Return an array with all available mo-files (without file extension .mo)
	 * 
	 * @param none
	 * @return array $mofiles
	 */
	function getMos(){
		$this->getallMos();
		return $this->mofiles;
	}
	
	/**
	 * 
	 * Checks if a given mo-file exists
	 * 
	 * @param string $mofile
	 * @return bool true | false
	 * @todo Maybe file_exists is the better way to check if an file exists
	 */
	function findMo( $mofile ){
		$mofile = str_replace('.mo', '', $mofile);
		
		$this->getallMos();
		
		return in_array($mofile, $this->mofiles);
	}
	
	/**
	 * 
	 * Read all mo-files in $path
	 * 
	 * @param none
	 * @return array $mofiles
	 */
	function getallMos(){
		
		if( !empty( $this->mofiles ) ){
			return $this->mofiles;
		}
		
		// Find all mo-files
		$farray = $filearray = array();
		$filename = '';
		
		$filearray = pathinfo( $this->path );
		$dirname = $filearray['dirname'].'/'.$filearray['basename'];
		
		
		foreach (glob($dirname.'/*.mo') as $filename) {
    		$farray = pathinfo($filename);
    		$this->mofiles[] = $farray['filename'];
		}
		
		unset($filename, $farray, $filearray);
		
		return $this->mofiles;
	}
	
	/* --- Textdomain ---------------------------------------------- */
		
	/**
	 * 
	 * Returns a textdomain (domain & locale)
	 * If $domain is set, $textdomain will build with $domain and $locale.
	 * If $domain is not set, $textdomain will be returned. Even if $textdomain is empty or not set.
	 * 
	 * @param none
	 * @return $textdomain
	 */
	function getTextdomain(){
		if( $this->domain && !$this->textdomain ){
			$this->textdomain = $this->domain.'-'.$this->locale;
		}
		
		return $this->textdomain;
	}
	
	/**
	 * 
	 * Return the textdomain if found in $path. Else returns false
	 * 
	 * @param string $textdomain
	 * @return string textdomain | bool false
	 * @todo: Maybe it's easier to check this with $textdomain.'.mo' and file_exists
	 */
	function findTextdomain( $textdomain = '' ){
		
		$this->getallMos();

		if( in_array( $textdomain, $this->mofiles ) ){
			return $textdomain;
		}
		else {
			return false;
		}
	}
	
	function loadTextdomain( $domain = '' ){
		$this->setLocale( $this->locale );
		
		if( 'default' == $this->domain ){
			$this->textdomain = $this->locale;
		}
		else {
			$this->domain = $this->findDomain( $domain );
				if( !$this->domain ){
					wp_die( '<strong>Error:</strong> Domain \'<em>'.$domain.'</em>\' was not found.' );
				}

		$this->getTextdomain();
		}			
		
		load_textdomain($this->domain, $this->path.'/'.$this->textdomain.'.mo');
		
		return $this->isTextdomainLoaded( $this->domain );
	}
	
	/**
	 * 
	 * Load a textdomain by guessing the best domain (with the most translations)
	 * 
	 * @param none
	 * @return bool true | false
	 */
	function createTextdomain(){
		$this->domain = $this->guessDomain();
		
		$this->loadTextdomain( $this->domain );
	}
	
	/**
	 * 
	 * Checks if a textdomain was loaded
	 * 
	 * @param string $domain
	 * @return bool true | false
	 */
	function isTextdomainLoaded( $domain ){
		global $l10n;
		
		if( !isset( $l10n[ $domain ]) ){
			return false;
		}
		else {
			return true;
		}
	}
	
	/* --- Locale ---------------------------------------------- */
	
	/**
	 * 
	 * Return the loacale setting (xx_XX)
	 * If $locale was not set, locale is set by the WP function get_locale 
	 * 
	 * @param none
	 * @return string $locale
	 */
	function getLocale(){
		$this->setLocale( $this->locale );
		return $this->locale;
	}

	/**
	 * 
	 * Set $locale to the given argument. If no argument is given, the WP function get_locale is used
	 * If $locale is not a valid locale (xx_XX) false is returned
	 * 
	 * @param string $locale
	 * @return $locale
	 */
	function setLocale( $locale ){
		if( !$locale ){
			$this->locale = get_locale();
		}
		else {
			$this->locale = $this->validateLocale( $locale );
		}
		
		return $this->locale;
	}

	/**
	 * 
	 * Create an array with all available translations (xx_XX)
	 * 
	 * @param none
	 * @return array $all_locales
	 */
	function getallLocales(){
		if( !empty( $this->all_locales ) ){
			return $this->all_locales;
		}
		
		$this->getallMos();
		
		foreach( $this->mofiles as $filename ){
			$f = array();
			preg_match('/[a-z][a-z]_[A-Z][A-Z]/',$filename, $f);
			if( !empty( $f ) ){
				if( !in_array( $f[0], $this->all_locales ) ){
					$this->all_locales[] = $f[0];
				}
			}
		}
		
		return $this->all_locales;
	}
	
	/**
	 * 
	 * Checks if a locale exists in the locale-list
	 * 
	 * @param string $locale
	 * @return string $locale | bool false
	 */
	function findLocale( $locale ){
		$locale = $this->validateLocale( $locale );
			// if $locale is not al valid string with format xx_XX, return false
			if( !$locale ){
				return false;
			}
		
		$this->getallLocales();

		if( in_array( $locale, $this->all_locales ) ){
			return $locale;
		}
		else {
			return false;
		}
		
	}
	
	/**
	 * 
	 * Checks if $locale have format xx_XX
	 * 
	 * @param string $locale
	 * @return string $locale | bool false
	 */
	function validateLocale( $locale ){
		if( preg_match('/[a-z][a-z]_[A-Z][A-Z]/',$locale) ){
			return $locale;
		}
		else {
			 return false;
		}
	}

	/* --- Domain ---------------------------------------------- */	
	
	/**
	 * 
	 * Return the domain part of a textdomain
	 * 
	 * @param none
	 * @return string $domain
	 */
	function getDomain(){
		if( !$this->domain && $this->textdomain ){
			$this->domain = preg_replace('/-[a-z][a-z]_[A-Z][A-Z]/', '', $this->textdomain);
		}
		
		return $this->domain;
	}
	
	/**
	 * 
	 * Set the domain part of a textdomain
	 * 
	 * @param string $domain
	 * @return void
	 */
	function setDomain( $domain ){
		$this->domain = $domain;		
	}
	
	/**
	 * 
	 * Create an array with all available domains
	 * 
	 * @param none
	 * @return array $all_domains
	 */
	function getallDomains(){
		if( !empty( $this->all_domains ) ){
			return $this->all_domains;
		}
		
		$this->getallMos();
		
		foreach( $this->mofiles as $mo ){
			if( !preg_match('/-?[a-z][a-z]_[A-Z][A-Z]/', $mo) ){
				continue;
			}
			
			$mo = preg_replace('/-?[a-z][a-z]_[A-Z][A-Z]/', '', $mo);
			 if( 0 == strlen($mo) ) {
			 	$mo = 'basic translation';
			 }
			
			if( !in_array( $mo, $this->all_domains) ){
				$this->all_domains[] = $mo;
			}
		}
		
		return $this->all_domains;
	}
	
	/**
	 * 
	 * Checks if a domain exists in the domain-list
	 * 
	 * @param string $domain
	 * @return string $domain | bool false
	 */
	function findDomain( $domain ){
		$this->getallDomains();
		
		if( in_array( $domain, $this->all_domains ) ){
			return $domain;
		}
		else {
			return false;
		}
	}
	
	/**
	 * 
	 * Guess a valid domain
	 * 
	 * @param none
	 * @return string $bestguess
	 */
	function guessDomain(){
		$mo = '';
		$mo_w = '';
		
		$this->getallMos();
		
		foreach( $this->mofiles as $mo ){
			if( !preg_match('/-?[a-z][a-z]_[A-Z][A-Z]/', $mo) ){
				continue;
			}
			
			$mo_w = preg_match('/-?[a-z][a-z]_[A-Z][A-Z]/', $mo);
			$mo = preg_replace('/-?[a-z][a-z]_[A-Z][A-Z]/', '', $mo);
				if( 0 == strlen($mo) ) {
					$mo = '-';
				}
			
			if( !key_exists($mo, $this->guesseddomains) ){
				$this->guesseddomains[$mo] = 1;
			}
			else{	
			 	$this->guesseddomains[$mo]++;
			 	// if the locale-part of a mo-file match the locale, it's fit better and so we raise the count
			 	if( $this->locale == $mo_w ){
			 		$this->guesseddomains[$mo]++;
			 	}
			}
		}
		
		if($this->debug)
			return $this->guesseddomains;
			
		arsort($this->guesseddomains);

		$bestguess = key($this->guesseddomains);

		if('-' == $bestguess){
		 	$bestguess = 'default';
		 }

		 unset($mo, $mo_w);
		return $bestguess;
	}
}
?>